package app;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import action.Action;
import action.SqlJob;
import action.TimeAction;
import connect.CodecFactory;
import connect.MyIoHandler;

public class App
{
	// 呼吸
	static int TIMEER = 60;

	static App instance;
	/** 配置文件解析 */
	public ServerConfig sc;
	/** 服务器接收器 */
	public NioSocketAcceptor accept;
	/** 执行器 */
	ScheduledThreadPoolExecutor executor;
	/** 数据库执行器 */
	ThreadPoolExecutor sqlPool;
	/** 数据库连接 */
	public BasicDataSource dataSource;
	/** 持有链接 */
	public Map<Integer, IoSession> connects = new HashMap<Integer, IoSession>();
	/***/
//	public Map<Integer, Player> pid_players = new HashMap<Integer, Player>();
//
//	public Map<Integer, Player> sid_players = new HashMap<Integer, Player>();

	public void start(String str)
	{

		executor = new ScheduledThreadPoolExecutor(1);
		loadConfig(str);

		startAcceptor();

		connectDb();

		sqlPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();

//		/** 启动定时类 */
//		TimeAction.init();
	}

	/** 链接数据库 */
	private void connectDb()
	{
		Properties p = new Properties();

		try
		{
			FileInputStream in = new FileInputStream(sc.db);
			p.load(in);
			in.close();
			BasicDataSource dataS = (BasicDataSource) BasicDataSourceFactory
					.createDataSource(p);
			if (dataS != null)
			{
				Connection conn = dataS.getConnection();
				conn.close();
			}
			dataSource = dataS;

		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/** 启动监听 */
	private void startAcceptor()
	{
		NioSocketAcceptor acceptor = new NioSocketAcceptor(Runtime.getRuntime()
				.availableProcessors() + 10);
		acceptor.setHandler(new MyIoHandler());
		acceptor.setDefaultLocalAddress(new InetSocketAddress("0.0.0.0",
				sc.port));
		ProtocolCodecFactory factory = new CodecFactory();
		acceptor.getFilterChain().addLast("codec",
				new ProtocolCodecFilter(factory));
		acceptor.getSessionConfig().setTcpNoDelay(true);
		acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);// 读写通道均在10
		// 秒内无任何操作就进入空闲状态
		accept = acceptor;
		try
		{
			acceptor.bind();
			System.err.println("启动服务器监听端口 :" + sc.port);
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/** 加载配置文件 */
	private void loadConfig(String str)
	{
		sc = new ServerConfig(str);
	}

	public static App getInstance()
	{
		if (instance == null)
		{
			instance = new App();
		}
		return instance;
	}

	public void pushAction(Action action)
	{
		if (action instanceof SqlJob)
		{
			sqlPool.execute(action);

		} else if (action instanceof TimeAction)
		{
			TimeAction ta = (TimeAction) action;
			executor.scheduleAtFixedRate(action, 0, ta.CD,
					TimeUnit.MILLISECONDS);
			System.err.println(System.currentTimeMillis() + "kaishi");
		} else
		{
			if(executor == null)
			{
				System.err.println("executor="+null);
			}
			executor.execute(action);
		}
	}

	public void removePlayer(IoSession session)
	{
//		Player player = sid_players.remove(session.hashCode());
//		pid_players.remove(player.pid);
	}

	public Connection getSqlConnection()
	{
		try
		{
			return dataSource.getConnection();
		} catch (SQLException e)
		{
			e.printStackTrace();
		}
		return null;
	}
}
